"""
目录扫描服务

提供高级的目录扫描、文件分类和管理功能。
"""

import asyncio
import json
from typing import Dict, List, Any, Optional
from pathlib import Path
from datetime import datetime
import logging

from src.core.di import Injectable, Inject, Service
from src.modules.scanners import (
    MediaDirectoryScanner,
    SmartFileClassifier,
    FileManager,
    ScanResult,
    FileInfo,
    ClassificationRule
)


@Service("directory_service")
class DirectoryService:
    """
    目录扫描服务
    
    提供高级的目录扫描、文件分类和管理功能。
    """
    
    def __init__(self,
                 scanner: MediaDirectoryScanner = Inject(MediaDirectoryScanner),
                 classifier: SmartFileClassifier = Inject(SmartFileClassifier),
                 file_manager: FileManager = Inject(FileManager),
                 config: Dict[str, Any] = Inject("config"),
                 logger: logging.Logger = Inject("logger")):
        self.scanner = scanner
        self.classifier = classifier
        self.file_manager = file_manager
        self.config = config
        self.logger = logger
        
        # 服务配置
        self.service_config = config.get("directory_service", {})
        self.auto_classify = self.service_config.get("auto_classify", True)
        self.auto_organize = self.service_config.get("auto_organize", False)
        self.save_scan_results = self.service_config.get("save_scan_results", True)
        self.results_dir = Path(self.service_config.get("results_dir", "output/scan_results"))
        
        # 创建结果目录
        if self.save_scan_results:
            self.results_dir.mkdir(parents=True, exist_ok=True)
    
    async def scan_and_classify(self, 
                              directory: str, 
                              **kwargs) -> Dict[str, Any]:
        """
        扫描目录并分类文件
        
        Args:
            directory: 目录路径
            **kwargs: 扫描和分类参数
        
        Returns:
            扫描和分类结果
        """
        self.logger.info(f"扫描并分类目录: {directory}")
        
        start_time = datetime.now()
        
        try:
            # 1. 扫描目录
            self.logger.info("开始扫描目录...")
            scan_result = await self.scanner.scan(directory, **kwargs)
            
            if scan_result.total_files == 0:
                self.logger.warning("未找到任何文件")
                return {
                    "success": True,
                    "scan_result": scan_result.to_dict(),
                    "classification_result": None,
                    "organization_result": None
                }
            
            # 2. 提取元数据（如果启用）
            if kwargs.get("extract_metadata", False):
                self.logger.info("提取文件元数据...")
                await self.scanner._extract_metadata_for_files(scan_result.files)
            
            # 3. 分类文件（如果启用）
            classification_result = None
            if self.auto_classify or kwargs.get("classify", False):
                self.logger.info("开始分类文件...")
                classified_files = await self.classifier.batch_classify(scan_result.files)
                scan_result.files = classified_files
                
                # 更新分类统计
                scan_result.category_stats = {}
                for file_info in scan_result.files:
                    category = file_info.category.value
                    scan_result.category_stats[category] = scan_result.category_stats.get(category, 0) + 1
                
                classification_result = {
                    "classified_files": len(classified_files),
                    "category_distribution": scan_result.category_stats,
                    "average_confidence": sum(f.confidence for f in classified_files) / len(classified_files) if classified_files else 0
                }
            
            # 4. 组织文件（如果启用）
            organization_result = None
            if self.auto_organize or kwargs.get("organize", False):
                output_dir = kwargs.get("output_dir")
                if output_dir:
                    self.logger.info("开始组织文件...")
                    organization_result = await self.file_manager.organize_files(
                        scan_result.files, output_dir, **kwargs
                    )
            
            # 5. 保存结果
            if self.save_scan_results:
                await self._save_scan_results(scan_result, directory)
            
            # 计算总耗时
            end_time = datetime.now()
            total_duration = (end_time - start_time).total_seconds()
            
            result = {
                "success": True,
                "scan_result": scan_result.to_dict(),
                "classification_result": classification_result,
                "organization_result": organization_result,
                "total_duration": total_duration,
                "timestamp": end_time.isoformat()
            }
            
            self.logger.info(f"扫描和分类完成，耗时 {total_duration:.2f}秒")
            return result
            
        except Exception as e:
            error_msg = f"扫描和分类失败: {e}"
            self.logger.error(error_msg)
            return {
                "success": False,
                "error": error_msg,
                "timestamp": datetime.now().isoformat()
            }
    
    async def batch_scan_directories(self, 
                                   directories: List[str], 
                                   **kwargs) -> Dict[str, Any]:
        """
        批量扫描多个目录
        
        Args:
            directories: 目录路径列表
            **kwargs: 扫描参数
        
        Returns:
            批量扫描结果
        """
        self.logger.info(f"批量扫描 {len(directories)} 个目录")
        
        results = {}
        total_files = 0
        total_errors = 0
        
        # 并发扫描
        max_concurrent = kwargs.get("max_concurrent", 3)
        semaphore = asyncio.Semaphore(max_concurrent)
        
        async def scan_single_directory(directory: str):
            async with semaphore:
                try:
                    result = await self.scan_and_classify(directory, **kwargs)
                    return directory, result
                except Exception as e:
                    self.logger.error(f"扫描目录失败 {directory}: {e}")
                    return directory, {"success": False, "error": str(e)}
        
        # 创建并发任务
        tasks = [scan_single_directory(directory) for directory in directories]
        
        # 等待所有任务完成
        scan_results = await asyncio.gather(*tasks, return_exceptions=True)
        
        # 处理结果
        for result in scan_results:
            if isinstance(result, Exception):
                self.logger.error(f"批量扫描任务失败: {result}")
                total_errors += 1
            else:
                directory, scan_result = result
                results[directory] = scan_result
                
                if scan_result.get("success"):
                    scan_data = scan_result.get("scan_result", {})
                    total_files += scan_data.get("total_files", 0)
                else:
                    total_errors += 1
        
        summary = {
            "total_directories": len(directories),
            "successful_scans": len([r for r in results.values() if r.get("success")]),
            "failed_scans": total_errors,
            "total_files_found": total_files,
            "results": results
        }
        
        self.logger.info(f"批量扫描完成: 成功 {summary['successful_scans']}/{len(directories)} 个目录")
        
        return summary
    
    async def create_product_directory_structure(self, base_path: str) -> Dict[str, Any]:
        """
        创建标准的商品目录结构
        
        Args:
            base_path: 基础路径
        
        Returns:
            创建结果
        """
        self.logger.info(f"创建商品目录结构: {base_path}")
        
        # 标准商品目录结构
        structure = {
            "未分类": {},
            "产品展示": {
                "主图": {},
                "细节图": {},
                "功能展示": {}
            },
            "产品使用": {
                "使用教程": {},
                "应用场景": {},
                "效果展示": {}
            },
            "模特试穿": {
                "正面": {},
                "侧面": {},
                "背面": {},
                "细节": {}
            },
            "AI素材": {
                "生成图片": {},
                "生成视频": {},
                "合成素材": {}
            },
            "背景素材": {
                "纯色背景": {},
                "场景背景": {},
                "纹理背景": {}
            },
            "宣传素材": {
                "广告视频": {},
                "宣传图片": {},
                "营销素材": {}
            }
        }
        
        try:
            created_dirs = await self.file_manager.create_directory_structure(base_path, structure)
            
            # 创建README文件
            readme_content = self._generate_directory_readme()
            readme_path = Path(base_path) / "README.md"
            with open(readme_path, 'w', encoding='utf-8') as f:
                f.write(readme_content)
            
            return {
                "success": True,
                "base_path": base_path,
                "created_directories": created_dirs,
                "structure": structure,
                "readme_created": str(readme_path)
            }
            
        except Exception as e:
            error_msg = f"创建目录结构失败: {e}"
            self.logger.error(error_msg)
            return {
                "success": False,
                "error": error_msg
            }
    
    async def add_classification_rule(self, rule_config: Dict[str, Any]) -> bool:
        """
        添加自定义分类规则
        
        Args:
            rule_config: 规则配置
        
        Returns:
            是否添加成功
        """
        try:
            from src.modules.scanners.base import FileCategory
            
            rule = ClassificationRule(
                name=rule_config.get("name", ""),
                description=rule_config.get("description", ""),
                category=FileCategory(rule_config.get("category", "unclassified")),
                file_patterns=rule_config.get("file_patterns", []),
                path_patterns=rule_config.get("path_patterns", []),
                priority=rule_config.get("priority", 0),
                confidence_boost=rule_config.get("confidence_boost", 0.0)
            )
            
            self.classifier.add_rule(rule)
            self.logger.info(f"添加分类规则: {rule.name}")
            
            return True
            
        except Exception as e:
            self.logger.error(f"添加分类规则失败: {e}")
            return False
    
    async def _save_scan_results(self, scan_result: ScanResult, directory: str) -> None:
        """保存扫描结果"""
        try:
            # 生成文件名
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            dir_name = Path(directory).name
            filename = f"scan_{dir_name}_{timestamp}.json"
            
            output_path = self.results_dir / filename
            scan_result.save_to_file(str(output_path))
            
            self.logger.info(f"扫描结果已保存: {output_path}")
            
        except Exception as e:
            self.logger.error(f"保存扫描结果失败: {e}")
    
    def _generate_directory_readme(self) -> str:
        """生成目录说明文档"""
        return """# 商品素材目录结构说明

## 目录结构

### 📁 未分类
存放尚未分类的素材文件。

### 📁 产品展示
存放产品展示相关的素材：
- **主图**: 产品主要展示图片/视频
- **细节图**: 产品细节特写
- **功能展示**: 产品功能演示

### 📁 产品使用
存放产品使用场景素材：
- **使用教程**: 产品使用教程视频
- **应用场景**: 产品应用场景展示
- **效果展示**: 使用效果对比

### 📁 模特试穿
存放模特试穿素材：
- **正面**: 正面试穿效果
- **侧面**: 侧面试穿效果
- **背面**: 背面试穿效果
- **细节**: 试穿细节展示

### 📁 AI素材
存放AI生成的素材：
- **生成图片**: AI生成的图片素材
- **生成视频**: AI生成的视频素材
- **合成素材**: AI合成的复合素材

### 📁 背景素材
存放背景相关素材：
- **纯色背景**: 纯色背景素材
- **场景背景**: 场景背景素材
- **纹理背景**: 纹理背景素材

### 📁 宣传素材
存放宣传营销素材：
- **广告视频**: 广告宣传视频
- **宣传图片**: 宣传海报图片
- **营销素材**: 其他营销素材

## 使用说明

1. 将素材文件放入对应的分类目录
2. 使用MixVideo系统自动扫描和分类
3. 系统会根据文件名、路径等特征自动分类
4. 可以手动调整分类结果

## 注意事项

- 保持文件名的规范性，有助于自动分类
- 定期整理和清理无用文件
- 备份重要素材文件
"""
    
    async def get_directory_statistics(self, directory: str) -> Dict[str, Any]:
        """获取目录统计信息"""
        try:
            scan_result = await self.scanner.scan(directory, recursive=True)
            
            stats = {
                "total_files": scan_result.total_files,
                "total_size": sum(f.size for f in scan_result.files),
                "file_types": scan_result.type_stats,
                "categories": scan_result.category_stats,
                "largest_files": sorted(scan_result.files, key=lambda f: f.size, reverse=True)[:10],
                "newest_files": sorted(scan_result.files, key=lambda f: f.modified_time or datetime.min, reverse=True)[:10]
            }
            
            return stats
            
        except Exception as e:
            self.logger.error(f"获取目录统计失败: {e}")
            return {"error": str(e)}
